import React from 'react'
import style from './style'
import cx from 'classnames'
import { error, Button, Link, FileUpload, SelectList } from '../'
import util from '../util'
import _ from '../../util'
import tc from 'textarea-caret'
import emojis from '../emoji'
import twemoji from 'twemoji'

// require("babel-polyfill");

const IMAGES_PATH = process.env.NODE_ENV === 'production'? './static/images': './static/src/images'
const DEFAULT_CONTENT = '分享图片'

window.twemoji = twemoji

export default
class TweetInput extends React.Component {

  requestAt = false
	pos = {}

	init = {
		// 0: 初始化
		// 1: extend
		// 2: extend + colored + actions
		// 3: extend + no-colored + actions
		status: 3,
		// 上传图片
		upload: false,
		showList: false,
    post: '',
		// emoji panel
		emoji: false,
    disabled: true,
    query: ''
	}

	state = this.init

	uploaded = []
  selectMap = {}

	static defaultProps = {
		onFocus: () => {},
		onBlur: () => {},
		onChange: () => {},
		onKeyUp: () => {},
		handleFileChange: () => {},
		handleFileUpload: () => {},
	}

	// public
	focus() {
    this.setState({
      status : 2
    })
    this.refs.input.focus()
	}
  blur() {
    this.setState({
      status : 3
    })
    this.refs.input.blur()
  }

	// public
	setAt(atUser) {
    const { fullName } = atUser
    this.requestAt = true
		this.setState({
			post: `@${ fullName } `
		})
    /*
		this.props.fetchAtList(fullName, (users=[]) => {
			const find = users.filter(user => user.fullName == fullName)[0]
			if (find) {
				this.selectMap[fullName] = find
			}
		})
    */
    this.selectMap[fullName] = atUser
	}

	handleSubmit() {
		const { post } = this.state

    const format = 
      str => str
        .replace(/[^\s\n](@[^@\s\n]+)/g, (whole, match) => whole.replace(match, ' ' + match))
        .trim()

    this.props.onSubmit({ 
			images: this.uploaded,
      content: format(post) , 
			selectMap: this.selectMap
		}, () => {
			this.clear()
			this.resetUpload()
		}, () => {
      this.reset()
			this.resetUpload()
		})
	}

	resetUpload() {
		if (this.props.pic) {
			if (this.refs.upload) {
				this.refs.upload.reset()
			}
		}
	}

	reset() {
    this.clear()
		this.setState({
			...this.state,
			...this.init
		})
	}

	clear() {
    this.uploaded = []
    this.refs.upload && this.refs.upload.reset()
		this.setState({
			post: '',
			upload: false,
      emoji: false,
      disabled: true
		})
	}

	handleFocus(e) {
		let nextStatus
		const { status } = this.state

		if (status === 0) {
			this.setState({
				status: 1
			})

			setTimeout(() => {
				this.setState({
					status: 2
				})
			}, this.props.multi? 100: 200)
		} else if (status === 3) {
			this.setState({
				status: 2
			})
		}

		this.props.onFocus()
	}

  close = e => {
    if (this.requestAt) return
    let el = e.target
    while(el && el !== document.body && !~el.className.indexOf(style.actions) && !~el.className.indexOf(style['emoji-panel'])) {
      el = el.parentNode
    }

    if (el === document.body || !el) {
      if (_.isNull(this.state.post)) {
        setTimeout(() => {
          this.setState({
            status: 0,
            emoji: false
          })
        }, 150)
      } else {
        setTimeout(() => {
          this.setState({
            status: 3
          })
        }, 150)
      }
    }
    //_.unbind(document, 'click', this.close)
  }

	handleBlur() {
    //if (this.props.autoClose) {
      //_.bind(document, 'click', this.close)
    //} 

    if (this.requestAt) {
      this.requestAt = false
      this.props.onBlur()
      return 
    }
    this.setState({
			status : 3,
			query: "",
      showList : false // 关闭selectList 
    })
		this.props.onBlur()
	}

  handleChange = e => {
		const { value } = e.target
		this.props.onChange(value)
    this.setState({
      post: value
		}, ::this.checkDisable)

		this.handleSearch();		
  }

	handleClick() {
		this.handleSearch()
	}

	handleKeyUp(e) {
		const { which } = e
		if (which === 16 || which === 13) return
		this.handleSearch();
	}

	handleSearch() {
		const el = this.refs.input
		const { value } = el
		const pos = this.pos  = util.getCursorPos(el)
		const { start, end } = pos
		const leftPart = value.slice(0, start)
		const rightPart = value.slice(start)
		const match = leftPart.match(/@([^@\s\n]*)$/)
		/* 
			此处正则判断，在edge下为null的情况下无法输入，Chrome下则可行
			不同浏览器对onkeyup和onchange的解释不同
			edge中若keyup执行return后则不会在执行ochange
		*/
		if (match === null) {
			return this.hideList()
		}

		const query = match[1] || ''
		this.setState({ query })

		util.throttle(
			() => {
				this.props.fetchAtList(query)
			}, 300
		)

    let { top, left } = tc(el, end - query.length)

    const showList = match !== null
    let listPosition = { left: left+'px' }

    if (showList) {
      // 计算位置
      const { clientHeight } = document.documentElement
      const { top:_top } = el.getBoundingClientRect()

      /*
      // 列表向上
      if (_top + 71 > clientHeight/2) {
        listPosition.bottom = '100%'
        listPosition.marginBottom = '-4px'
      } else {
      */
      listPosition.top = top + (this.props.multi? 28: 24) - el.scrollTop + 'px'
        //}
    }

    this.setState({
      showList,
      listPosition
    })

    if (match) {
      this.caret = {
        start,
        end
      }
    }
	}

	hideList() {
		this.setState({
			showList: false
		})
	}

	requestUpload() {
		this.refs.upload.upload()
	}

	toggleEmoji() {
		this.setState({
			emoji: !this.state.emoji
		})
	}

	handleFileChange(file, success, files) {

    this.setState({
      disabled: true
    })

		if (!this.state.upload) {
			this.setState({
				upload: true
			})
		}
		this.props.handleFileChange(file, success)
	}

	handleFileUpload(files) {
		this.uploaded = files
    if (_.isNull(this.state.post)) this.setState({
      post: DEFAULT_CONTENT
    })

    if (!files.length) {
      if (this.state.post === DEFAULT_CONTENT) {
        this.setState({
          post: ''
        }, this.checkDisable.bind(this))
      }
    }

    this.checkDisable()
	}

  checkDisable() {
    let flag = this.state.disabled;
    if (this.props.pic) {
      if ((!this.uploaded.length && _.isNull(this.state.post)) || this.uploaded.length < this.refs.upload.files.length) {
        flag = true;
      } else {
        flag = false;
      } 
    } else if (_.isNull(this.state.post)) {
      flag = true;
    } else {
      flag = false;
    }
    this.setState({
      disabled: flag
    })
    this.props.checkDisable && this.props.checkDisable(flag);
  }

	handleListSelect(selected) {
    this.hideList()
    const obj = (this.props.atList[this.state.query] || [])[selected]
    const el = this.refs.input
    let { start, end } = util.getCursorPos(el)
    
    if (start == null) {
      start = this.caret.start
      end = this.caret.end
      el.focus()
    }

    const { value } = el

    this.setState({
      post: value.slice(0, start).replace(/(@[^@\s\n]*)$/, (whole, _match) => whole.replace(_match, '@' + obj.fullName)) +' '+ value.slice(start)
    })

    setTimeout(() => {
      el.selectionStart = start + obj.fullName.length +1
      el.selectionEnd = end + obj.fullName.length +1
			this.pos = {
				start: el.selectionStart,
				end: el.selectionEnd
			}
    }, 0)

		this.selectMap[obj.fullName] = obj
		if(this.props.onChange){ // 点击选中@的人后立刻回调值
			this.props.onChange(value.slice(0, start).replace(/(@[^@\s\n]*)$/, (whole, _match) => whole.replace(_match, '@' + obj.fullName)) +' '+ value.slice(start));
		}
	}

	handleEmojiClick(v) {
		const el = this.refs.input
		const { start, end } = this.pos
		const { post } = this.state
    let _start = start

    if(!_start) {
      _start = post.length
    }

    const newPost = post.slice(0, _start) +  twemoji.convert.fromCodePoint(v) + post.slice(_start)

		this.setState({
      post: newPost,
      //emoji: false
		})

		el.focus()


		setTimeout(() => {
      el.selectionStart = el.selectionEnd = start? (start + 2): newPost.length
		}, 0)

    if (start) {
      this.pos = {
        start: start + 2
      }
    } else {
      this.pos = {}
    }

    this.setState({
      disabled: false
    },::this.checkDisable)
	}

	renderSelects() {
		return (
			<SelectList
				data={this.props.atList[this.state.query]}
				show={this.state.showList}
				pos={this.state.listPosition}
				handleSelect={::this.handleListSelect}
				query={this.state.query}
			/>
		)
	}

	render() {
		const { pic, className, multi, label, isShowEmoji, ...others } = this.props
		const { status, emoji } = this.state
		const input = React.createElement(multi? 'textarea': 'input', {
		  ...others,
			ref: 'input',
			className: style.input,
			placeholder: label,
			onFocus: ::this.handleFocus,
			onBlur: ::this.handleBlur,
			// onKeyUp: ::this.handleKeyUp,
			onClick: ::this.handleClick,
			onChange: ::this.handleChange,
			value: this.state.post
		})
		const actions = status >= 2? (
			<div 
				className={style.actions} onMouseDown={(e) => {e.preventDefault()}}>
				<ul className={style.addons}>
					<li>
						{
							isShowEmoji === "false" ? null : <Link icon="smile" onClick={::this.toggleEmoji}/>
						}
						{
							pic?
							<Link icon="pic" onClick={::this.requestUpload}/>
							: null
						}
					</li>
				</ul>
        {
          this.props.noBtn ? null : 
          <Button 
            disabled={this.state.disabled}
            onClick={::this.handleSubmit}
            className={style.submit}
            onMouseDown={util.preventDefaultEvent}
            label="发布"/>
        }
				
			</div>
		): null
		return (
			<div className={cx({
				[className]: className,
				[style.root]: true,
				[style.showUpload]: this.state.upload,
			  [style.focused]: status > 0,
			  [style.blured]: status === 3
			})}
        onMouseDown={util.preventDefaultEvent}
      >
			 <div className={cx({
				 [style.wrapper]: true,
				 [style.multi]: multi
			 })}>
					{ input }
					{ actions }
					{ this.renderSelects() }
				</div>
				{
					pic?
					<FileUpload
						ref="upload"
						className={cx({
							[style.upload]: true,
							[style.showUpload]: this.state.upload
						})}
						size="54"
						row="7"
						margin="13"
						multi
						onUpload={::this.handleFileUpload}
						onChange={::this.handleFileChange}
            accept="image/gif,image/jpeg,image/jpg,image/png"
					/>
					: null
				}
				{
					emoji?
					<div className={style['emoji-panel']} onMouseDown={(e) => {e.preventDefault()}}>
						<ul >
							{
								emojis.map((v, i) => (
									<li 
										onClick={() => this.handleEmojiClick(v)}
										key={i}
                    dangerouslySetInnerHTML={{__html: twemoji.parse(twemoji.convert.fromCodePoint(v), {folder: '72x72', size: '72', base: `${IMAGES_PATH}/emoji/` })}}/>
								))
							}
						</ul>
            <Link 
              icon="arrow" 
              className={style['hide-emoji']} 
              iconRotate="-180" onClick={() => { this.setState({ emoji: false }) }}
            />
					</div>: null
				}
			</div>
		)
	}
}
